package com.yeyks.common.utils;

import ch.qos.logback.core.pattern.ConverterUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yeyks.common.base.Arguments;
import org.springframework.beans.BeanUtils;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author fuchangshuai
 * @time 2019/2/22 7:48 PM
 */
public class ObjectConvertUtil {

    /**
     * 把source对象转换成另一个clazz类型的对象, 两种对象相同属性的类型，必须相同，否则会抛出BeansException异常。
     * 内部采用BeanUtils.copyProperties(source, object)来实现属性复制。
     *
     * @param source 源对象
     * @param clazz  目标对象的类型
     * @return
     */
    public static <T> T convertObject(Object source, Class<T> clazz) {
        if (source == null) {
            return null;
        }
        T object = BeanUtils.instantiate(clazz);
        BeanUtils.copyProperties(source, object);
        return object;
    }

    /**
     * 拷贝list,只支持List<Object>结构；不支持list里面的元素为集合类型
     *
     * @param source 源list数据
     * @param clazz  需要转换成的list元素类型
     * @return 转换后的列表对象
     */
    public static <T> List<T> convertList(List<?> source, Class<T> clazz) {
        if (source == null) {
            return null;
        }
        List<T> list = new ArrayList<T>();
        for (Object element : source) {
            list.add(convertObject(element, clazz));
        }
        return list;
    }

    /**
     * 字符串列表转换为整型列表
     *
     * @param values 字符串列表
     * @return 整型列表
     */
    public static List<Long> convertList(List<String> values) {
        try {
            List<Long> result = new ArrayList<>();
            for (String value : values) {
                result.add(Long.valueOf(value));
            }
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将对象转成map
     *
     * @param obj
     * @return
     */
    public static Map<String, Object> objectToMap(Object obj) {
        Map<String, Object> result = Maps.newHashMap();
        try {
            BeanInfo info = Introspector.getBeanInfo(obj.getClass());
            for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
                Method reader = pd.getReadMethod();
                if (reader != null && !pd.getName().equals("class")) {
                    result.put(pd.getName(), reader.invoke(obj));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return result;
    }

    /**
     * 将Map<String, Object> --> Map<String, String>
     * @param data
     * @return
     */
    public static Map<String, String> changeDataType(Map<String, Object> data){

        Map<String, String> map = Maps.newHashMap();

        for(Map.Entry<String, Object> mapStr : data.entrySet()){

            String value = mapStr.getValue().toString();
            if(Arguments.strIsNull(value)){
                map.put(mapStr.getKey(), "");
                continue;
            }
            map.put(mapStr.getKey(), value);
        }

        return map;
    }

    /**
     * Map转实体对象
     *
     * @param map       Map对象
     * @param beanClass 实体类型
     * @return T 实体
     */
    public static <T> T mapToBean(Map<String, Object> map, Class<T> beanClass) {
        if (null == map) {
            return null;
        }
        try {
            T obj = beanClass.newInstance();
            Field[] fields = obj.getClass().getDeclaredFields();
            for (Field field : fields) {
                int mod = field.getModifiers();
                if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
                    continue;
                }
                //获取私有属性必须设置
                field.setAccessible(true);
                //属性赋值
                field.set(obj, map.get(field.getName()));
            }
            return obj;
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取类中被static和final修饰的属性值集合
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> List<String> getPropertyValueToList(Class<T> clazz) {
        try {
            Field[] fields = clazz.getDeclaredFields();
            List<String> lists = Lists.newArrayList();
            for (Field field : fields) {
                //获取该field的值
                if (Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers())) {
                    Object object = field.get(clazz);
                    if (null != object) {
                        lists.add(String.valueOf(object));
                    }
                }
            }
            return lists;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Lists.newArrayList();
    }
}
